package zombiedefense.sprites;

import java.awt.Image;
import java.awt.Point;
import zombiedefense.framework.EffectManager;
import zombiedefense.sound.ZombieDefenseSoundManager;
import static zombiedefense.util.MathEx.loadImageFromJar;

public enum Gun {

    pistol(Gun.pistolImage, new Point(2, 0), new Point(2, 12),
	    Gun.type_pistol, EffectManager.pistolFlash,15, 100,
	    500,600,1,Math.toRadians(5), 1.0, "9mm pistol",0,5,
	    "m4a1_fire","reload2"),
    
    smg(Gun.smgImage, new Point(2, 1), new Point(2, 22),
	    Gun.type_rifle, EffectManager.pistolFlash,30, 120,
	    80,1700, 1,Math.toRadians(8), 5.0, "Submachine-gun",150,25,
	    "mp5_fire","reload1"),
    
    shotgun(Gun.shotgunImage, new Point(3, 0), new Point(3,30),
	    Gun.type_rifle, EffectManager.shotgunFlash,8, 64,
	    750,3000, 8, Math.toRadians(20), 5.0, "Pump-action shotgun",200,50,
	    "shotgun_fire","shotgun_load"),
    
    assaultRifle(Gun.assaultRifleImage,new Point(2,1),new Point(2,27),
	    Gun.type_rifle,EffectManager.assaultRifleFlash,60,240,
	    100,1700,1,Math.toRadians(3),5.0,"Assault Rifle",1000,200,
	    "ak47_fire","reload1"),
    
    lmg(Gun.lmgImage,new Point(7,1),new Point(7,42),
	    Gun.type_rifle,EffectManager.machineGunFlash,200,600,
	    100,1700,1,Math.toRadians(10),10.0,"Light Machine-gun",5000,500,
	    "lmg_fire","reload1"),
    
    chaingun(Gun.chaingunImage,new Point(7,1),new Point(7,37),
	    Gun.type_rifle,EffectManager.machineGunFlash,250,1000,
	    50,1700,1,Math.toRadians(5),15.0,"Chain-gun",10000,1000,
	    "minigun_fire","reload1");
    
    
    //gun images
    private static Image[] gunimages = {
        loadImageFromJar("/images/pistol.png"),
        loadImageFromJar("/images/shotgun.png"),
        loadImageFromJar("/images/smg.png"),
        loadImageFromJar("/images/assaultrifle.png"),
        loadImageFromJar("/images/lmg.png"),
        loadImageFromJar("/images/chaingun.png")
    };
    private static final byte pistolImage = 0;
    private static final byte shotgunImage = 1;
    private static final byte smgImage = 2;
    private static final byte assaultRifleImage = 3;
    private static final byte lmgImage = 4;
    private static final byte chaingunImage = 5;
    //gun types - used to position gun onscreen
    public static final byte type_pistol = 0;
    public static final byte type_rifle = 1;
    
    private long dryFireLength = 500;
    private String dryFireSound = "dryfire";
    private byte image;
    private Point barrel;
    private Point pivot;
    private byte type;
    private int loadedAmmo;
    private int stowedAmmo;
    private int clipsize;
    private int maxStowed;
    private long firinginterval;
    private long reloadinterval;
    private byte flash;
    private double accuracy;
    private int numbulletsfired;
    private double damage;
    private String name;
    private int gunCost;
    private int ammoCost;
    private String fireSound;
    private String reloadSound;
    private boolean locked = true;

    Gun(byte image, Point barrel, Point pivot, byte type, byte flash, int clipsize,
	    int maxStowed,long firinginterval,long reloadinterval, int numbulletsfired,
            double accuracy, double damage, String name,int gunCost,int ammoCost,
	    String fireSound,String reloadSound) {
        this.image = image;
        this.barrel = barrel;
        this.pivot = pivot;
        this.type = type;
        this.loadedAmmo = clipsize;
        this.stowedAmmo = maxStowed;
        this.clipsize = clipsize;
        this.maxStowed = maxStowed;
        this.firinginterval = firinginterval;
	this.reloadinterval = reloadinterval;
        this.flash = flash;
        this.accuracy = accuracy;
        this.numbulletsfired = numbulletsfired;
        this.damage = damage;
        this.name = name;
        this.gunCost = gunCost;
        this.ammoCost = ammoCost;
	this.fireSound = fireSound;
	this.reloadSound = reloadSound;
    }
    
    /**
     * Fires this gun and returns whether or not
     * a shot was actually fired.
     * @return 
     */
    public boolean fire(){
	if(loadedAmmo >= 1){
	    //play firing sound
	    ZombieDefenseSoundManager.playSound(fireSound);
	    
	    loadedAmmo--;
	    return true;
	}else{
	    //play dry fire sound
	    ZombieDefenseSoundManager.playSound(dryFireSound);
	    return false;
	}
    }
    
    /**
     * Modifies this gun's data to simulate a reload.
     * Returns whether or not reloading has completed,
     * or if additional calls will be necessary.
     * @return 
     */
    public void reload(){
        //make sure reloading is necessary
	if(loadedAmmo < clipsize){
            
            //make sure reloading is possible
	    if(stowedAmmo > 0){
                    //play reload sound
                    ZombieDefenseSoundManager.playSound(reloadSound);
                
		    int amountToLoad = Math.min(clipsize - loadedAmmo,stowedAmmo);
		    loadedAmmo += amountToLoad;
		    stowedAmmo -= amountToLoad;
		}
	}
    }
    
    public void refill(){
	stowedAmmo = maxStowed;
    }

    public String getName() {
        return name;
    }

    public double getAccuracy() {
        return accuracy;
    }

    public Point getBarrel() {
        return barrel;
    }

    public long getReloadInterval() {
	return reloadinterval;
    }

    public int getClipsize() {
        return clipsize;
    }

    public double getDamage() {
        return damage;
    }

    public long getFiringinterval() {
        return firinginterval;
    }

    public byte getFlash() {
        return flash;
    }

    public int getAmmoCost() {
        return ammoCost;
    }

    public int getGunCost() {
        return gunCost;
    }

    
    
    public int getLoadedAmmo() {
        return loadedAmmo;
    }

    public int getMaxStowed() {
        return maxStowed;
    }

    public int getNumbulletsfired() {
        return numbulletsfired;
    }

    public Point getPivot() {
        return pivot;
    }

    public int getStowedAmmo() {
        return stowedAmmo;
    }
    
    public long getDryFiringInterval(){
	return dryFireLength;
    }

    public byte getType() {
        return type;
    }

    public void setLocked(boolean t) {
        locked = t;
    }

    public boolean isLocked() {
        return locked;
    }

    public int getWidth() {
        return gunimages[image].getWidth(null);
    }

    public int getHeight() {
        return gunimages[image].getHeight(null);
    }

    public Image getImage() {
        return gunimages[image];
    }
}